package com.huage.courseplatform.satoken.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huage.courseplatform.application.mapper.ConfigMapper;
import com.huage.courseplatform.application.model.entity.SysConfig;
import com.huage.courseplatform.framework.constant.StatusConstants;
import com.huage.courseplatform.framework.utils.EncryptUtil;
import com.huage.courseplatform.satoken.mapper.RoleMapper;
import com.huage.courseplatform.satoken.mapper.UserMapper;
import com.huage.courseplatform.satoken.model.entity.Role;
import com.huage.courseplatform.satoken.model.entity.User;
import com.huage.courseplatform.satoken.model.vo.UserVO;
import com.huage.courseplatform.satoken.service.UserService;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.UUID;

import static com.huage.courseplatform.framework.constant.StatusConstants.ACCOUNT_NORMAL;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Resource
    private UserMapper userMapper;

    @Resource
    private RoleMapper roleMapper;

    @Resource
    private ConfigMapper configMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = "Service:UserService:page", allEntries=true)
    public User addUserAndRole(User user, List<String> roleIds) {
        if(StringUtils.isNotBlank(user.getEmail())){
            User oldUser = lambdaQuery().eq(User::getEmail,user.getEmail()).one();
            Assert.isNull(oldUser,"邮箱已存在");
        }
        if(StringUtils.isNotBlank(user.getPhone())){
            User oldUser = lambdaQuery().eq(User::getPhone,user.getPhone()).one();
            Assert.isNull(oldUser,"手机已存在");
        }
        if(StringUtils.isNotBlank(user.getOpenId())){
            User oldUser = lambdaQuery().eq(User::getOpenId,user.getOpenId()).one();
            Assert.isNull(oldUser,"微信已绑定");
        }

        //密码随机盐值加密
        String salt = UUID.randomUUID().toString();
        //获取配置表默认密码
        String defaultPassword = configMapper.selectOne(new QueryWrapper<SysConfig>().eq("code","DEFAULT_PASSWORD")).getValue();
        String password = EncryptUtil.getInstance().MD5(defaultPassword,salt);
        user.setPassword(password);
        user.setPasswordSalt(salt);
        user.setStatus(ACCOUNT_NORMAL);


        baseMapper.insert(user);
        if(!CollectionUtils.isEmpty(roleIds)){
            //先删除关联关系再添加
            userMapper.delUserRoleByUserId(user.getId());
            roleIds.forEach(roleId->{
                userMapper.addUserAndRole(user.getId(),roleId);
            });
        }
        return user;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Caching(evict={@CacheEvict(cacheNames = "Service:RoleService:userId", key = "#user.id"),
            @CacheEvict(cacheNames = "Service:UserService:id", key = "#user.id"),
            @CacheEvict(cacheNames = "Service:UserService:page", allEntries=true),})
    public User updateUserAndRole(User user, List<String> roleIds) {
        if(StringUtils.isNotBlank(user.getEmail())){
            User oldUser = lambdaQuery().eq(User::getEmail,user.getEmail()).one();
            Assert.isNull(oldUser,"邮箱已存在");
        }
        if(StringUtils.isNotBlank(user.getPhone())){
            User oldUser = lambdaQuery().eq(User::getPhone,user.getPhone()).one();
            Assert.isNull(oldUser,"手机已存在");
        }
        if(StringUtils.isNotBlank(user.getOpenId())){
            User oldUser = lambdaQuery().eq(User::getOpenId,user.getOpenId()).one();
            Assert.isNull(oldUser,"微信已绑定，请修改openId");
        }

        baseMapper.updateById(user);

        //先删除关联关系再添加
        userMapper.delUserRoleByUserId(user.getId());
        roleIds.forEach(roleId->{
            userMapper.addUserAndRole(user.getId(),roleId);
        });



        return user;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Caching(evict={@CacheEvict(cacheNames = "Service:RoleService:id", key = "#id"),
                    @CacheEvict(cacheNames = "Service:UserService:id", key = "#id"),
                    @CacheEvict(cacheNames = "Service:UserService:page", allEntries=true),})
    public String removeUserAndRoleById(String id) {
        removeById(id);
        userMapper.delUserRoleByUserId(id);
        return id;
    }

    @Override
    @Cacheable(cacheNames="Service:UserService:id",key = "#id",unless="#result == null")
    public UserVO getUserAndRoleById(String id) {
        User user = getById(id);
        if(ObjectUtils.isEmpty(user)){
            return null;
        }
        List<Role> roleList = roleMapper.getRoleListByUserId(id);
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user,userVO);
        userVO.setRoleList(roleList);
        return userVO;
    }

    @Override
    public void updatePassword(String userId, String oldPassword, String newPassword) {
        User user = lambdaQuery().eq(User::getId,userId).one();
        if(ObjectUtils.isEmpty(user)){
            Assert.isTrue(false,"找不到指定用户");
        }
        String password = EncryptUtil.getInstance().MD5(oldPassword,user.getPasswordSalt());
        if(!password.equals(user.getPassword())){
            Assert.isTrue(false,"用户密码错误");
        }
        String newEncorePassword = EncryptUtil.getInstance().MD5(newPassword,user.getPasswordSalt());
        lambdaUpdate().set(User::getPassword,newEncorePassword).eq(User::getId,userId).update();
        StpUtil.logout(userId);
    }

    @Override
    public void resetPassword(String userId) {
        //密码随机盐值加密
        String salt = UUID.randomUUID().toString();
        //获取配置表默认密码
        String defaultPassword = configMapper.selectOne(new QueryWrapper<SysConfig>().eq("code","DEFAULT_PASSWORD")).getValue();
        String password = EncryptUtil.getInstance().MD5(defaultPassword,salt);
        lambdaUpdate().set(User::getPassword,password).set(User::getPasswordSalt,salt).eq(User::getId,userId).update();
        StpUtil.logout(userId);
    }

    @Override
    @Cacheable(cacheNames="Service:UserService:page",key = "'page:'+#page.pages+'-'+#page.size+'qw:'+#queryWrapper.expression",unless="#result == null")
    public Page<UserVO> getUserAndRolesPage(Page page, QueryWrapper<UserVO> queryWrapper) {
        return userMapper.getUserAndRolesPage(page,queryWrapper);
    }


}
